#region license
# This file is part of Grawlix.
# 
# Grawlix is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as
# published by the Free Software Foundation, either version 3 of
# the License, or (at your option) any later version.
# 
# Grawlix is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public
# License along with Grawlix.  If not, see
# <http://www.gnu.org/licenses/>.
#endregion

"""A client-side game loader designed for testing purposes."""

namespace Grawlix.Client
import Grawlix.Meta
import Grawlix.Services
import System
import System.Threading

final class TestGameLoader(ServiceBase, IGameLoader):
"""A game loader designed to fail immediately if the initial load fails."""
	
	def constructor(
		[required] world as string,
		[required] gameFactory as IGameFactory):
	"""
	Initializes the new loader.
	Param world: The name of the local world to test.
	Param gameFactory: The factory used to create new Games.
	"""
		_world = world
		_gameFactory = gameFactory
	
	[lock(_lockObj)]
	def LoadLocal():
	"""Starts loading the local game. Fails upon second call."""
		try:
			if _game is not null:
				Quit()
			configFile = "World/${_world}/" + \
				"Client/Properties/ServiceConfiguration.xml"
			configBuilder = \
				ServiceConfigurationBuilder.FromFile(_world, configFile)
			searchPaths = "World/${_world}/Client;Library/Client"
			_game = _gameFactory.Create(
				_world,
				configBuilder.Configuration,
				searchPaths)
			_loading = true
		except exception:
			Quit()
			log Warn, "An error occurred in " + \
				"World ${_world} during load. " + \
				"Quitting.\n" + \
				exception
	
	[lock(_lockObj)]
	def Host(
		[required] worldName as string,
		port as int):
	"""
	Emulates a game locally for others to connect to.
	Param worldName: The name of world to host.
	Param port: The port to host on.
	Raises NotImplementedException:
		This function is not implemented by the test loader.
	"""
		if port <= 0 or port > 65535:
			raise ArgumentException(
				"Valid ports are between 1 and 65535, inclusive. " +
				"${port} was specified.",
				"port")
		raise NotImplementedException(
			"Hosting a network game is not supported by the test loader.")
	
	[lock(_lockObj)]
	def Connect([required] hostname as string, port as int):
	"""
	Starts loading a game over the network.
	Param hostname: The name of the host or IP address.
	Param port: The port on the host to connect to.
	Raises NotImplementedException:
		This function is not implemented by the test loader.
	"""
		if port <= 0 or port > 65535:
			raise ArgumentException(
				"Valid ports are between 1 and 65535, inclusive. " +
				"${port} was specified.",
				"port")
		raise NotImplementedException(
			"Joining a network game is not supported by the test loader.")
	
	[lock(_lockObj)]
	def CancelLoad():
	"""
	Causes the current game to quit.
	Raises NotImplementedException:
		This function is not implemented by the test loader.
	"""
		raise NotImplementedException(
			"Cancelling a load is not supported by the test loader.")
	
	def Quit():
	"""Starts the process of exiting the game."""
		Thread.VolatileWrite(_hasQuit, 1)
		log Debug, "Quit was requested."
	
	[lock(_lockObj)]
	def Update(elapsed as timespan) as Game:
	"""
	Update the game loader.
	Param elapsed: The amount of time since last update.
	Returns: The currently loaded game.
	Remarks:
		For front-end use only.
		
		Will cause errors if not called by the front end, as
		it may invalidate a game that is already in use.
	"""
		if _game is null:
			log Warn, "Game null during update in test loader."
			Quit()
			return null
		
		if _game.Target.Ready:
			_loading = false
			return _game.Target
		return null
	
	Loading:
	"""An indicator describing whether a game is being loaded."""
		[lock(_lockObj)]
		get:
			return _loading
	
	HasQuit:
	"""An indicator describing whether the game is shutting down."""
		get:
			return Thread.VolatileRead(_hasQuit) != 0
	
	private _hasQuit as int
	"""An indicator describing whether the game is shutting down."""
	
	private _lockObj = object()
	"""The object to synchronize with."""
	
	private _game as ExternalProxy[of Game]
	"""The currently active game."""
	
	private _loading as bool
	"""The game that is loading. It will become current when activated."""
	
	private _gameFactory as IGameFactory
	"""The factory used to create game objects."""
	
	private _world as string
	"""The name of the default world to load."""
	
	private static final _builtInWorldName = "Built-In"
	"""The name of the built in world."""
